﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System;
using System.Collections.Generic;
using ScrumTable.Common;
using ScrumTable.Common.Collections;
using ScrumTable.Common.Data;
using ScrumTable.Common.Net;
using ScrumTable.Common.Test;
using ScrumTable.DL.Data.Generic.Cache;

#endregion

namespace ScrumTable.DL.Data.Generic.Test
{
    /// <summary>
    /// This is the test class for IDataLoader class.
    /// </summary>
    public class ResourceManager
    {
        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------

        private const string TestImageFile = "ScrumTable.DL.Data.Generic.TestImg.jpg";

        private readonly CacheContext _context;


        //--------------------------------------------------------------------
        // Cache Teams
        //--------------------------------------------------------------------

        internal const string Team1DisplayName = "Team 1";
        internal const string Team1BackEndId = "Team1BackEndId";
        internal const string Team2DisplayName = "Team 2";
        internal const string Team2BackEndId = "Team2BackEndId";

        //--------------------------------------------------------------------
        // Cache Members
        //--------------------------------------------------------------------

        internal static readonly Uri Member1PictureUrl = new Uri("http://www.example.com/picture1.jpg");
        internal const string Member1DisplayName = "domain\\user1";
        internal const string Member1MailAddress = "user1@example.com";
        internal const string Member1AccountName = "user1";
        internal const string Member1Domain = "domain";
        internal const string Member1InternalId = "45";

        internal readonly CacheMember Member1;
        internal readonly CacheMember Member2;
        internal readonly CacheMember Member3;
        internal readonly CacheMember Member4;
        internal readonly CacheMember Member5;

        //--------------------------------------------------------------------
        // Cache Iterations
        //--------------------------------------------------------------------

        internal const int Iteration1Id = 0;
        internal const int Iteration2Id = 1;
        internal const int Iteration3Id = 2;

        internal const string Iteration1Name = "Iteration 1";
        internal const string Iteration1IterationPath = "Project 1\\Iteration 1";
        internal static readonly DateTime Iteration1StartDate = new DateTime(2010, 10, 29);
        internal static readonly DateTime Iteration1EndDate = new DateTime(2010, 11, 29);

        internal readonly CacheIteration Iteration1Proj1;
        internal readonly CacheIteration Iteration2Proj1;
        internal readonly CacheIteration Iteration1Proj2;

        //--------------------------------------------------------------------
        // Cache User Stories
        //--------------------------------------------------------------------

        internal const int UserStory1Id = 0;
        internal const int UserStory2Id = 1;
        internal const int UserStory3Id = 2;

        internal readonly CacheWorkItem UserStory1;
        internal readonly CacheWorkItem UserStory2;
        internal readonly CacheWorkItem UserStory3;

        //--------------------------------------------------------------------
        // Cache Tasks
        //--------------------------------------------------------------------

        internal const int Task1Id = 10;
        internal const int Task2Id = 11;
        internal const int Task3Id = 12;

        internal readonly CacheWorkItem Task1;
        internal readonly CacheWorkItem Task2;
        internal readonly CacheWorkItem Task3;

        //--------------------------------------------------------------------
        // Cache Bugs
        //--------------------------------------------------------------------

        internal const int Bug1Id = 20;
        internal const int Bug2Id = 21;
        internal const int Bug3Id = 31;

        internal readonly CacheWorkItem Bug1;
        internal readonly CacheWorkItem Bug2;
        internal readonly CacheWorkItem Bug3;

        //--------------------------------------------------------------------
        // Cache Attachments
        //--------------------------------------------------------------------

        internal readonly CacheAttachment Attachment1;
        internal readonly CacheAttachment Attachment2;
        internal readonly CacheAttachment Attachment3;
        internal readonly CacheAttachment Attachment4;

        //--------------------------------------------------------------------
        // Cache Revisions
        //--------------------------------------------------------------------

        internal readonly CacheWorkItemRevision Revision1;
        internal readonly CacheWorkItemRevision Revision2;

        //--------------------------------------------------------------------
        // Cache Projects
        //--------------------------------------------------------------------

        internal static readonly int Project1IterationCount = 2;
        internal static readonly int Project1UserStoryCount = 2;
        internal static readonly int Project1UserStory1TaskCount = 0;
        internal static readonly int Project1UserStory2TaskCount = 1;
        internal static readonly int Project1UserStory2BugCount = 1;
        internal static readonly int Project1UserStory3BugCount = 2;
        internal static readonly int Project1Iteration1UserStory3TaskCount = 2;
        internal static readonly int Project1Iteration1UserStoryCount = 1;
        internal static readonly int Project1MemberCount = 3;
        internal static readonly int Project1TeamCount = 2;
        internal static readonly int Project1TypeCount = 2;
        internal static readonly int Project1UserStory1RevisionCount = 2;

        internal static readonly int Project1IdentityCount = 33;

        internal const int ProjectCount = 2;
        internal const string Project1Name = "Project 1";
        internal static readonly ServiceRegistration Project1WssRegistration;
        internal static readonly ServiceRegistration Project1RsRegistration;

        internal readonly CacheProject Project1;
        internal readonly CacheProject Project2;

        internal readonly CacheTeam Team1;
        internal readonly CacheTeam Team2;

        internal readonly CacheReport Report1Proj1;
        internal readonly CacheReport Report2Proj1;

        internal readonly TestFieldDefinitionSet FieldDefinitionsProj1;
        internal readonly TestFieldDefinitionSet FieldDefinitionsProj2;

        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------

        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        static ResourceManager()
        {
            Project1WssRegistration = new ServiceRegistration("http://www.example.com/project1/wssuri");
            Project1RsRegistration = new ServiceRegistration("http://www.example.com/project1/rsuri");
        }

        internal ResourceManager(CacheContext context)
        {
            PreCondition.AssertNotNull(context, "context");

            _context = context;

            //----------------------------------------------------------------
            // Create Team Instances
            //----------------------------------------------------------------

            Team1 = _context.ElementFactory.CreateTeam(0, Team1DisplayName, Team1BackEndId);
            Team2 = _context.ElementFactory.CreateTeam(1, Team2DisplayName, Team2BackEndId);

            //----------------------------------------------------------------
            // Create Member Instances
            //----------------------------------------------------------------

            Member1 = _context.ElementFactory.CreateMember(0, Member1DisplayName, Member1MailAddress, Member1AccountName, Member1Domain, Member1InternalId, true, new[] { Team1.ReferenceName, Team2.ReferenceName });
            Member1.PictureUrl = Member1PictureUrl;
            Member2 = _context.ElementFactory.CreateMember(1, "domain\\user2", "user2@example.com", "user2", "domain", null, false, new[] { Team1.ReferenceName });
            Member2.PictureUrl = new Uri("http://www.example.com/picture2.jpg");
            Member3 = _context.ElementFactory.CreateMember(2, "domain\\user3", "user3@example.com", "user3", "domain", null, false, new[] { Team2.ReferenceName });
            Member3.PictureUrl = new Uri("http://www.example.com/picture3.jpg");

            Member4 = _context.ElementFactory.CreateMember(3, Member1DisplayName, Member1MailAddress, Member1AccountName, Member1Domain, Member1InternalId, true, null);
            Member4.PictureUrl = Member1PictureUrl;
            Member5 = _context.ElementFactory.CreateMember(4, "domain\\user2", "user2@example.com", "user2", "domain", null, false, null);
            Member5.PictureUrl = new Uri("http://www.example.com/picture2.jpg");

            FieldDefinitionsProj1 = new TestFieldDefinitionSet(_context, new[] { Member1, Member2, Member3 });
            FieldDefinitionsProj2 = new TestFieldDefinitionSet(_context, new[] { Member4, Member5 });

            //----------------------------------------------------------------
            // Create Attachment Instances
            //----------------------------------------------------------------

            Attachment1 = _context.ElementFactory.CreateAttachment("My First Attachment.txt", 1, "This is an attachment", new Uri(@"C:\temp\MyAttachment1.txt"));
            Attachment2 = _context.ElementFactory.CreateAttachment("My Second Attachment.img", 2, "This is an attachment", new Uri(@"C:\temp\MyAttachment2.img"));
            Attachment3 = _context.ElementFactory.CreateAttachment("My Third Attachment.txt", 3, "This is an attachment", new Uri(@"C:\temp\MyAttachment3.txt"));
            Attachment4 = _context.ElementFactory.CreateAttachment("My Forth Attachment.img", 4, "This is an attachment", new Uri(@"C:\temp\MyAttachment4.img"));

            //----------------------------------------------------------------
            // Create Revision Instances
            //----------------------------------------------------------------

            Revision1 = _context.ElementFactory.CreateRevision(0, "Test Revision 0", "History Text 0");
            Revision2 = _context.ElementFactory.CreateRevision(1, "Test Revision 1", "History Text 1");

            //----------------------------------------------------------------
            // Create Iteration Instances
            //----------------------------------------------------------------

            Iteration1Proj1 = _context.ElementFactory.CreateIteration(
                "Iteration 0",
                0,
                Iteration1Id,
                Iteration1Name,
                Iteration1IterationPath,
                Iteration1StartDate,
                Iteration1EndDate);

            Iteration2Proj1 = _context.ElementFactory.CreateIteration(
                "Iteration 1",
                1,
                Iteration2Id,
                "Iteration 2",
                "Project 1\\Iteration 2",
                new DateTime(2010, 11, 29),
                new DateTime(2010, 12, 29));

            Iteration1Proj2 = _context.ElementFactory.CreateIteration(
                "Iteration 2",
                2,
                Iteration3Id,
                "Iteration 1",
                "Project 2\\Iteration 1",
                new DateTime(2010, 10, 29),
                new DateTime(2010, 11, 29));

            //----------------------------------------------------------------
            // Create User Story Instances
            //----------------------------------------------------------------

            UserStory1 = _context.ElementFactory.CreateWorkItem(
                FieldDefinitionsProj1.UserStoryType,
                UserStory1Id,
                "User Story 1",
                0,
                CacheIdentity.DefaultId,
                "InProgress",
                "As user I want to have [ANY THING] in the [DIAGRAM] so that I easily see that [SOMETHING] is used instead of the two [DIAGRAMS].",
                Member2.ReferenceName,
                GetUserStoryValues(),
                new CacheWorkItemLink[0],
                new CacheWorkItemLink[0],
                new CacheAttachment[] { Attachment1 },
                new CacheWorkItemRevision[] { Revision1, Revision2});

            UserStory2 = _context.ElementFactory.CreateWorkItem(
                FieldDefinitionsProj1.UserStoryType,
                UserStory2Id,
                "User Story 2",
                0,
                CacheIdentity.DefaultId,
                "Active",
                "As user I want to have [ANY THING] in the [DIAGRAM] so that I easily see that [SOMETHING] is used instead of the two [DIAGRAMS].",
                Member2.ReferenceName,
                GetUserStoryValues(),
                new CacheWorkItemLink[0],
                new CacheWorkItemLink[] { _context.ElementFactory.CreateWorkItemLink(Task1Id), _context.ElementFactory.CreateWorkItemLink(Bug1Id) },
                new CacheAttachment[] { Attachment2, Attachment3 },
                new CacheWorkItemRevision[0]);

            UserStory3 = _context.ElementFactory.CreateWorkItem(
                FieldDefinitionsProj1.UserStoryType,
                UserStory3Id,
                "User Story 3",
                0,
                Iteration1Id,
                "Closed",
                "As user I want to have [ANY THING] in the [DIAGRAM] so that I easily see that [SOMETHING] is used instead of the two [DIAGRAMS].",
                Member2.ReferenceName,
                GetUserStoryValues(),
                new CacheWorkItemLink[0],
                new CacheWorkItemLink[]
                    {
                        _context.ElementFactory.CreateWorkItemLink(Task2Id),
                        _context.ElementFactory.CreateWorkItemLink(Task3Id),
                        _context.ElementFactory.CreateWorkItemLink(Bug2Id)
                        /* expected: inconsistent work item links, UserStory 3 should reference Bug3Id, the datalayer has to create this link automatically */ 
                    },
                new CacheAttachment[0],
                new CacheWorkItemRevision[0]);

            //----------------------------------------------------------------
            // Create Task Instances
            //----------------------------------------------------------------

            Task1 = _context.ElementFactory.CreateWorkItem(
                FieldDefinitionsProj1.TaskType,
                Task1Id,
                "Task 1",
                0,
                CacheIdentity.DefaultId,
                "Active",
                "This text describes the task.",
                string.Empty,
                GetTaskValues(),
                new List<CacheWorkItemLink> { _context.ElementFactory.CreateWorkItemLink(UserStory2Id) },
                new List<CacheWorkItemLink>(),
                new List<CacheAttachment> { Attachment4 },
                new CacheWorkItemRevision[0]);

            Task2 = _context.ElementFactory.CreateWorkItem(
                FieldDefinitionsProj1.TaskType,
                Task2Id,
                "Task 2",
                0,
                Iteration1Id,
                "Active",
                "This text describes the task.",
                string.Empty,
                GetTaskValues(),
                new List<CacheWorkItemLink> { _context.ElementFactory.CreateWorkItemLink(UserStory3Id) },
                new List<CacheWorkItemLink>(),
                new List<CacheAttachment>(),
                new CacheWorkItemRevision[0]);

            Task3 = _context.ElementFactory.CreateWorkItem(
                FieldDefinitionsProj1.TaskType,
                Task3Id,
                "Task 3",
                0,
                Iteration1Id,
                "Closed",
                "This text describes the task.",
                string.Empty,
                GetTaskValues(),
                new List<CacheWorkItemLink> { _context.ElementFactory.CreateWorkItemLink(UserStory3Id) },
                new List<CacheWorkItemLink>(),
                new List<CacheAttachment>(),
                new CacheWorkItemRevision[0]);

            //----------------------------------------------------------------
            // Create Bug Instances
            //----------------------------------------------------------------

            Bug1 = _context.ElementFactory.CreateWorkItem(
                FieldDefinitionsProj1.BugType,
                Bug1Id,
                "Bug 1",
                0,
                CacheIdentity.DefaultId,
                "Active",
                "This text describes the bug.",
                string.Empty,
                GetBugValues(),
                new List<CacheWorkItemLink> { _context.ElementFactory.CreateWorkItemLink(UserStory2Id) },
                new List<CacheWorkItemLink>(),
                new List<CacheAttachment> { Attachment1, Attachment2 },
                new CacheWorkItemRevision[0]);

            Bug2 = _context.ElementFactory.CreateWorkItem(
                FieldDefinitionsProj1.BugType,
                Bug2Id,
                "Bug 2",
                0,
                Iteration1Id,
                "Active",
                "This text describes the bug.",
                string.Empty,
                GetBugValues(),
                new List<CacheWorkItemLink> { _context.ElementFactory.CreateWorkItemLink(UserStory3Id) },
                new List<CacheWorkItemLink>(),
                new List<CacheAttachment>(),
                new CacheWorkItemRevision[0]);

            Bug3 = _context.ElementFactory.CreateWorkItem(
                FieldDefinitionsProj1.BugType,
                Bug3Id,
                "Bug 3",
                0,
                CacheIdentity.DefaultId, // expected: inconsistent iteration path with parent (UserStory 3)
                "Resolved",
                "This text describes the bug.",
                string.Empty,
                GetBugValues(),
                new List<CacheWorkItemLink> { _context.ElementFactory.CreateWorkItemLink(UserStory3Id) },
                new List<CacheWorkItemLink>(),
                new List<CacheAttachment>(),
                new CacheWorkItemRevision[0]);

            //----------------------------------------------------------------
            // Create Project Instances
            //----------------------------------------------------------------
            
            Report1Proj1 = _context.ElementFactory.CreateReport(
                "[Report 1]",
                "Report1",
                new Uri("Report1.jpg", UriKind.RelativeOrAbsolute),
                string.Empty,
                new[] { _context.ElementFactory.CreateFieldDefinition<NamedValue>("Name", "Name Field", DataType.String, null, null) });

            Report2Proj1 = _context.ElementFactory.CreateReport(
                "[Report 2]",
                "Report2",
                new Uri("Report2.jpg", UriKind.RelativeOrAbsolute),
                string.Empty,
                new[] { _context.ElementFactory.CreateFieldDefinition<NamedValue>(
                    "Name",
                    "Name Field",
                    DataType.String,
                    new NamedValue("Default", "0"),
                    new[] { new NamedValue("Default", "0"), new NamedValue("1", "1"), new NamedValue("2", "2") }) });

            //----------------------------------------------------------------
            // Create Project Instances
            //----------------------------------------------------------------

            Project1 = _context.ElementFactory.CreateProject(
                1,
                Project1Name,
                Project1WssRegistration,
                Project1RsRegistration,
                new[] { Team1, Team2 }, 
                FieldDefinitionsProj1.Members,
                FieldDefinitionsProj1.WorkItemTypes);

            Project2 = _context.ElementFactory.CreateProject(
                2,
                "Project 2",
                ServiceRegistration.Empty,
                ServiceRegistration.Empty,
                new[] { Team2 },
                FieldDefinitionsProj2.Members,
                FieldDefinitionsProj2.WorkItemTypes);
        }

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        internal string GetTestImageFilePath(string testDir)
        {
            return ResourceUtil.CombineToProjectPath(testDir, TestImageFile);
        }

        internal void ImportProject1Data(CacheProject project)
        {
            IDictionary<int, CacheWorkItem> workItems = new Dictionary<int, CacheWorkItem>
                                                            {
                                                                {UserStory1.Id, UserStory1},
                                                                {UserStory2.Id, UserStory2},
                                                                {UserStory3.Id, UserStory3},
                                                                {Task1.Id, Task1},
                                                                {Task2.Id, Task2},
                                                                {Task3.Id, Task3},
                                                                {Bug1.Id, Bug1},
                                                                {Bug2.Id, Bug2},
                                                                {Bug3.Id, Bug3},
                                                            };

            project.ImportData(
                new[] {Iteration1Proj1, Iteration2Proj1},
                new[] {Report1Proj1, Report2Proj1},
                workItems);
        }

        internal void ImportProject2Data(CacheProject project)
        {
            project.ImportData(
                new[] { Iteration1Proj2 },
                null,
                new Dictionary<int, CacheWorkItem>());
        }


        internal ValueChain<string> GetIterationChain(CacheProject project, int iterationId)
        {
            return new ValueChain<string>(project.UniqueId, project.Iterations.TryGetById(iterationId).UniqueId);
        }

        internal ValueChain<string> GetUserStoryChain(CacheProject project, int userStoryId)
        {
            return new ValueChain<string>(project.UniqueId, project.Project.WorkItems.TryGetById(userStoryId).UniqueId);
        }

        internal ValueChain<string> GetUserStoryChain(CacheProject project, int iterationId, int userStoryId)
        {
            return new ValueChain<string>(GetIterationChain(project, iterationId), project.Project.WorkItems.TryGetById(userStoryId).UniqueId);
        }


        private IDictionary<string, object> GetUserStoryValues()
        {
            Dictionary<string, object> values = new Dictionary<string, object>();
            values[_context.Schema.UserStorySchema.Ranking.SchemaMappedName] = 0.0;
            values[_context.Schema.UserStorySchema.StoryPoints.SchemaMappedName] = 0.0;
            return values;
        }

        private IDictionary<string, object> GetBugValues()
        {
            Dictionary<string, object> values = new Dictionary<string, object>();
            values[_context.Schema.BugSchema.Ranking.SchemaMappedName] = 0.0;
            values[_context.Schema.BugSchema.Description] = "Bug";
            return values;
        }

        private IDictionary<string, object> GetTaskValues()
        {
            Dictionary<string, object> values = new Dictionary<string, object>();
            values[_context.Schema.TaskSchema[TestFieldDefinitionSet.ActivityFieldName].SchemaMappedName] = "Deployment";
            values[_context.Schema.TaskSchema.CompletedWork.SchemaMappedName] = 1.5;
            values[_context.Schema.TaskSchema.Estimate.SchemaMappedName] = 2.5;
            values[_context.Schema.TaskSchema[TestFieldDefinitionSet.PriorityFieldName].SchemaMappedName] = 5;
            values[_context.Schema.TaskSchema.Ranking.SchemaMappedName] = 10.0;
            values[_context.Schema.TaskSchema.RemainingWork.SchemaMappedName] = 5.5;
            return values;
        }

        #endregion

        #region Events
        //--------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------

        #endregion
    }
}
